package cn.harry.component.security.service;

import cn.harry.common.constant.CacheConstants;
import cn.harry.common.constant.CommonConstant;
import cn.harry.common.exception.ApiException;
import cn.harry.component.security.model.SysUserDetails;
import cn.harry.modular.system.domain.SysUser;
import cn.harry.modular.system.enums.StatusEnums;
import cn.harry.modular.system.exception.enums.SysExceptionEnum;
import cn.harry.modular.system.mapper.SysMenuMapper;
import cn.harry.modular.system.mapper.SysUserMapper;
import cn.harry.modular.system.mapper.SysUserRoleMapper;
import cn.hutool.core.bean.BeanUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;

/**
 * 用户详情服务
 *
 * @author harry
 * @公众号 Harry技术
 */
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    private final SysUserMapper sysUserMapper;
    private final SysMenuMapper sysMenuMapper;
    private final SysUserRoleMapper sysUserRoleMapper;

    @Override
    @Cacheable(value = CacheConstants.USER_DETAILS, key = "#username", unless = "#result == null ")
    public SysUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        // 获取登录用户信息
        SysUser user = sysUserMapper.selectByUsername(username);

        // 用户不存在
        if (BeanUtil.isEmpty(user)) {
            throw new ApiException(SysExceptionEnum.USER_NOT_EXIST);
        }
        Long userId = user.getUserId();

        // 用户停用
        if (StatusEnums.DISABLE.getKey().equals(user.getStatus())) {
            throw new ApiException(SysExceptionEnum.USER_DISABLED);
        }

        // 获取角色
        Set<String> roles = sysUserRoleMapper.listRoleKeyByUserId(userId);

        // 获取数据范围标识
        Integer dataScope = sysUserRoleMapper.getMaximumDataScope(roles);

        Set<String> permissions = new HashSet<>();
        // 如果 roles 包含 root 则拥有所有权限
        if (roles.contains(CommonConstant.SUPER_ADMIN_ROOT)) {
            permissions.add(CommonConstant.ALL_PERMISSION);
        } else {
            // 获取菜单权限标识
            permissions = sysMenuMapper.getMenuPermission(userId);
            // 过滤空字符串
            permissions.remove("");
        }

        return new SysUserDetails(user, permissions, roles, username, dataScope);
    }

}
